import Raphael from "raphael";
let paper = null;
let container_id = "";
let graphInstance = null;
let edgeColor = 'tomato'

/**
 * 初始化树节点和边到dom 
 * 
 * @param { String } containerId 容器ID
 * @param { Graph } graph 图形化容器实例
 * @param { Array } nodes 带坐标的节点
 * @param { Array } links 带坐标的边
 * @param { String } connector 连接线展示方式 当前仅支持 curve曲线  straight直线, 默认直线
 * @param { String } edgeColor 边的颜色 默认tomato
 * @returns { TTechnology }
 */
export const initDagreTree = ({ containerId="", graph = null, nodes = [], links = [], connector = 'straight', edgeColor = "tomato" }) => {
    container_id = `#${containerId}`;
    graphInstance = graph;
    edgeColor = edgeColor;

    const { clientWidth, clientHeight } = getElementRule(container_id);
    // 创建SVG画布，每次都会新增到容器顶部
    paper = new Raphael(containerId, clientWidth, clientHeight - 50)
    
    // 渲染节点和边
    renderView(nodes, links, connector)

    return paper
}

/**
 * 重新设置svg的视图属性，让内容居中显示
 */
export const resetViewBox = () => {
    const { clientWidth, clientHeight } = getElementRule(container_id);
    if (graphInstance) {
        // DagreJS图形的宽度和高度
        const graphWidth = graphInstance.graph().width;
        const graphHeight = graphInstance.graph().height;

        // 计算位移量
        const dx = (clientWidth - graphWidth) / 2;
        const dy = (clientHeight - graphHeight) / 2;

        // 设置viewBox保证内容完全展示
        const svg = paper.setViewBox(-dx, -dy, clientWidth, clientHeight)
    }
}



/**
 * 获取容器Dom
 * 
 * @param { String } element_Id 元素ID
 * @returns { Object } { clientWidth, clientHeight }
 */
export const getElementRule = (element_Id = "") => {
    const elementDom = document.querySelector(element_Id);
    if (!elementDom) {
        throw new Error(`The container id${ element_Id } is invalid or the page does not have a corresponding id container.`)
    }
    const { clientWidth, clientHeight } = elementDom;
    return {
        clientWidth, 
        clientHeight
    }
}

/**
 * 渲染节点和边
 * 
 * @param { Array } nodes 带坐标的节点
 * @param { Array } links 带坐标的边
 * @param { String } connector 连接线展示方式 当前仅支持 curve曲线  straight直线, 默认直线
 */
export const renderView  = (nodes = [], links = [], connector="straight") => {
    if (!paper) return
    let i = 0
    while (i < nodes.length) {
        // const rect = paper.rect(nodes[i].x, nodes[i].y, nodes[i].width, nodes[i].height, 5)
        // Paint布局（例如SVG和HTML）通常使用标准的盒子模型，元素的x和y位置从左上角开始计算。
        // 然而，DagreJS对位置的计算则略有不同，其x和y是基于元素的中心点进行的。
        // 需要转换元素x和y坐标才能对齐连线
        const rect = paper.rect(nodes[i].x - nodes[i].width / 2, nodes[i].y - nodes[i].height / 2, nodes[i].width, nodes[i].height, 5);
        const rectBox = rect.getBBox()
        rect.attr('stroke', edgeColor)
        rect.attr('stroke', 1)
        const { cx, cy, x:Rx, y:Ry, width, height }  = rectBox
        let textX = Rx + width / 2, textY = Ry + height / 2;
        const text = paper.text(textX, textY, nodes[i].label)
        text.attr('font-size', 18)
        text.attr('font-weight', '600')
        i++;
    }

    // 获取连接线数据
    const newLinks = linkConnector(connector, links)
    let j = 0;
    while (j < newLinks.length) {
        const path = paper.path(newLinks[j])
            path.attr('stroke', edgeColor)
            path.attr('stroke-width', 3)
        j++;
    }

    resetViewBox()
}

/**
 * 绘制线条模式
 * 当前仅支持 curve曲线  straight直线
 * 
 * @param { String } name 曲线名称 curve || straight
 * @param { Array } links 连接线集合
 */
export const linkConnector = (name = "straight", links = []) => {
    let newLineSet = []
    if (name == void 0) return links
    if (!Array.isArray(links)) {
        new Error('The connection line must be an array of objects')
    }
    if (links.length == 0) return []
    
    let i = 0;
    while (i < links.length) {
        const { points } = links[i];
        let _D = '';
        // 二次贝塞尔曲线只支持一个控制点，起始两个坐标
        if (points.length === 3) {
            for(let k = 0; k < points.length; k++) {
                // straight 
                if (name === 'straight') {
                    if (k === 0) {
                        _D += `M ${points[k].x} ${points[k].y} `
                    } else {
                        _D += `L ${points[k].x} ${points[k].y} `
                    }
                }
                // curve 
                if (name === 'curve') {
                    if (k === 0) {
                        _D += `M ${points[k].x} ${points[k].y} `
                    } else if (k === 1){
                        _D += `Q ${points[k].x} ${points[k].y} `
                    } else {
                        _D += `${points[k].x} ${points[k].y}`
                    }
                }  
            }
        } 
        if (points.length === 5) {
            for (let j = 0; j < points.length; j++) {
                // 五个坐标绘制成线段L
                // if (j === 0) {
                //     _D += `M ${points[j].x} ${points[j].y} `
                // } else {
                //     _D += `L ${points[j].x} ${points[j].y} `
                // }
                // 展示路径坐标点
                const circle = paper.circle(points[j].x, points[j].y, 5)
                circle.attr('fill', '#10AC84')

                // 五个点绘制会出现脱节问题
                // 测试绘制三次贝塞尔曲线，两个控制点，起点和终点
                if (j === 0) {
                    _D += `M${points[j].x},${points[j].y} `
                } else if (j === 1) {
                    _D += `C${points[j].x},${points[j].y} `
                } else if (j == 2) {
                    _D += `${points[j].x},${points[j].y} `
                } else if (j == 3) {
                    // _D += `${points[j].x},${points[j].y} `
                } else if (j == 4) {
                    _D += `${points[j].x},${points[j].y} `
                }

            }
            // console.log(_D, points, 212);
        }
        
        newLineSet.push(_D)
        i++;
    }
    
    return newLineSet
}